package com.hctrl.mybatis.metaObject.decorator;

import cn.hutool.core.util.ClassUtil;
import com.hctrl.mybatis.metaObject.handler.TypeHandler;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.reflection.*;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author hanchao
 * @version 1.0
 * @date 2022/5/24 22:41
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
public class MetaObjectDecorator {

    private MetaObject metaObject;
    private List<TypeHandler> typeHandlerList = new ArrayList<>();

    {
        //获取TypeHandler接口的所有子类
        String aPackage = ClassUtil.getPackage(TypeHandler.class);
        Set<Class<?>> classes = ClassUtil.scanPackage(aPackage);
        Set<Class<?>> collect = classes.stream().filter(sonClass -> {
            boolean allAssignableFrom = ClassUtil.isAllAssignableFrom(new Class[]{TypeHandler.class}, new Class[]{sonClass});
            //要将 本身排除
            return allAssignableFrom && sonClass != TypeHandler.class;
        }).collect(Collectors.toSet());
        try {
            for (Class<?> clazz : collect){
                Object o = clazz.newInstance();
                typeHandlerList.add((TypeHandler) o);
            }
        }catch (Exception e){
            System.out.println("类扫描异常");
        }
    }

    public void setValue(String name, Object value){
        try {
            metaObject.setValue(name,value);
        }catch (ReflectionException e){
            if (e.getCause().getMessage().equals("argument type mismatch")){
                Class<?> setterType = metaObject.getSetterType(name);
                for (TypeHandler handler : typeHandlerList){
                    if (handler.support(setterType)){
                        metaObject.setValue(name,handler.typeReplacement(value.toString()));
                    }
                }
            }
        }
    }
}
